/*******************************************************************************
 * Copyright (c) 2007 University of Oslo.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     University of Oslo - initial API and implementation
 *******************************************************************************/

package com.cea.papyrus.diagram.sequence.sedi.model.command;

import org.eclipse.uml2.uml.Message;
import org.eclipse.uml2.uml.MessageEnd;

/**
 * Command to move Messages.
 * 
 * <p>
 * The following fields must be set for the command to be successful:
 * </p>
 * <ul>
 * <li>Message
 * </ul>
 * 
 * <p>
 * The following fields must be set if the sender end should be moved.
 * <ul>
 * <li>SendPosition
 * </ul>
 * 
 * <p>
 * The following fields must be set if the receving end should be moved.
 * <ul>
 * <li>ReceivePosition
 * </ul>
 * 
 * @author Andreas Limyr
 * @author frankd@ifi.uio.no
 */
public class MoveMessageCommand extends AbstractMessageCommand {

	private Message message;
	private MessageEnd oldSendEvent, oldReceiveEvent;
	private MessageEndPosition oldSendPosition, oldReceivePosition;

	public void setMessage(final Message message) {
		this.message = message;
	}

	@Override
	public void execute() {
		if (sendPosition != null) {
			oldSendEvent = message.getSendEvent();
			removeMessage(oldSendEvent);
			oldSendPosition = removeMessageEnd(oldSendEvent);

			MessageEnd newSendEnd = createMessageEnd(sendPosition, true);
			message.setSendEvent(newSendEnd);
			newSendEnd.setMessage(message);
			sendMessage(newSendEnd, message.getSignature());
		}

		if (receivePosition != null) {
			oldReceiveEvent = message.getReceiveEvent();
			removeMessage(oldReceiveEvent);
			oldReceivePosition = removeMessageEnd(oldReceiveEvent);

			MessageEnd newReceiveEnd = createMessageEnd(receivePosition, false);
			message.setReceiveEvent(newReceiveEnd);
			newReceiveEnd.setMessage(message);
			receiveMessage(newReceiveEnd, message.getSignature());
		}
	}

	@Override
	public void undo() {
		if (sendPosition != null) {
			MessageEnd sendEnd = message.getSendEvent();
			removeMessageEnd(sendEnd);

			addMessageEnd(oldSendPosition, oldSendEvent, true);
			message.setSendEvent(oldSendEvent);
			oldSendEvent.setMessage(message);

			// transferMessageEndAttributes(sendEnd, oldSendEvent);

			oldSendEvent = null;
			oldSendPosition = null;
		}

		if (receivePosition != null) {
			MessageEnd receiveEnd = message.getReceiveEvent();
			removeMessageEnd(receiveEnd);

			addMessageEnd(oldReceivePosition, oldReceiveEvent, false);
			message.setReceiveEvent(oldReceiveEvent);
			oldReceiveEvent.setMessage(message);

			// transferMessageEndAttributes(receiveEnd, oldReceiveEvent);

			oldReceiveEvent = null;
			oldReceivePosition = null;
		}
	}

	@Override
	public void redo() {
		this.execute();
	}

	@Override
	public void dispose() {
		message = null;
		oldSendEvent = null;
		oldSendPosition = null;
		oldReceiveEvent = null;
		oldReceivePosition = null;
		super.dispose();
	}

	/*
	 * private void transferMessageEndAttributes(MessageEnd sourceEnd,
	 * MessageEnd targetEnd) { final boolean sourceIsMsgOccSpec = sourceEnd
	 * instanceof MessageOccurrenceSpecification; final boolean
	 * targetIsMsgOccSpec = targetEnd instanceof MessageOccurrenceSpecification;
	 * 
	 * if (sourceIsMsgOccSpec) { OccurrenceSpecification sourceOcc =
	 * (OccurrenceSpecification) sourceEnd; if (targetIsMsgOccSpec) {
	 * OccurrenceSpecification targetOcc = (OccurrenceSpecification) targetEnd;
	 * targetOcc.setEvent(sourceOcc.getEvent()); } else if (targetEnd instanceof
	 * Gate) { // noop } } else if (sourceEnd instanceof Gate) { if
	 * (targetIsMsgOccSpec) { MessageOccurrenceSpecification targetOccSpec =
	 * (MessageOccurrenceSpecification) targetEnd; // noop } else { // noop } } /*
	 * if (sourceEnd instanceof OccurrenceSpecification && targetEnd instanceof
	 * OccurrenceSpecification) { OccurrenceSpecification sourceOcc =
	 * (OccurrenceSpecification) sourceEnd; OccurrenceSpecification targetOcc =
	 * (OccurrenceSpecification) targetEnd;
	 * targetOcc.setEvent(sourceOcc.getEvent()); }* / }
	 */
}
